package com.yy.utils.file;


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
  
import java.awt.image.BufferedImage;  
import java.io.File;  
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import javax.imageio.ImageIO;  
import javax.imageio.ImageReadParam;  
import javax.imageio.ImageReader;  
import javax.imageio.stream.ImageInputStream;  
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.apache.log4j.Logger;

import com.yy.utils.DateUtils;
import com.yy.utils.PropertiesUtil;
import com.yy.utils.data.Base64Util;


/**
 * 图片输出工具类
 * @author yy
 * @date
 */
public class ImageUtil {
	private static final Logger log = Logger.getLogger(ImageUtil.class);
	
	public static String thumbnailSize200_200 = "_200x200";
	public static String thumbnailSize300_200 = "_300x200";
	public static String thumbnailSize500_200 = "_500x200";
	public static String thumbnailSize1000_1000 = "_1000x1000";
	public static String thumbnailSuffix = "_thumb";
	public static String directory = PropertiesUtil.getImgLocalPath();
	
	private static Boolean DEFAULT_FORCE = false;
	
	/**
	 * 生成带年月的文件目录,如D:\\files\\images\\banner\\2017\\05\\或/root/files/images/banner/2017/05/
	 * @param fileRootDir 存放文件的根路径,如/root/files/images或D:\\files\\images
	 * @param typeFolder 分类文件夹目录名
	 */
	public static String createFolder(String fileRootDir,String typeFolder){
			String fileDir=String.format("%s%s%s%s%s%s%s%s", fileRootDir,File.separator,typeFolder,File.separator,DateUtils.currentYearStr(),File.separator,DateUtils.currentSimpleMonthStr(),File.separator);
			File folder=new File(fileDir);
			//System.out.println("######createFolder: "+fileDir);
			if(!folder.isDirectory())folder.mkdirs();
			return fileDir;
	}
	/**
	* 判断年文件夹
	* @return 返回 <b>true </b>,否则为 <b>false </b>
	*/
	public static boolean isVirectoryYear() {
		String directory = ImageUtil.directory+DateUtils.currentYearStr();
		return new File(directory).isDirectory();
	}
	/**
	* 判断月文件夹
	* @return 返回 <b>true </b>,否则为 <b>false </b>
	*/
	public static boolean isVirectoryMonth() {
		String directory = ImageUtil.directory+DateUtils.currentYearStr();
		if(!isVirectoryYear()){
			//创建年文件夹
			new File(directory).mkdir();
			return new File(directory+File.separator+DateUtils.currentMonthStr()).isDirectory();			
		}
		return new File(directory+File.separator+DateUtils.currentMonthStr()).isDirectory();
	}
	/**
	* 判断文件夹是否存在
	* @param str 文件夹名称
	* @return 返回 <b>true </b>,否则为 <b>false </b>
	*/
	public static boolean isVirectory(String str) {
		String directory = ImageUtil.directory+str;
		return new File(directory).isDirectory();
	}
	
	/**
	* 创建年月文件目录
	* @return 返回 <b>true </b>,否则为 <b>false </b>
	*/
	public static String fonderVirectory(String str) {
		String directory = ImageUtil.directory+DateUtils.currentYearStr()+File.separator+DateUtils.currentMonthStr()+File.separator+str;
		if(!isVirectory(str)){
			//创建年文件夹
			new File(directory).mkdir();
			return directory;
		}
		return directory;
	}
	
	/**
	* 验证图片
	* 
	* @param imagePath 图片全路径
	* @return 如果是符合的字符串,返回 <b>true </b>,否则为 <b>false </b>
	*/
	public static Boolean image(String imagePath){
		File srcImg = new File(imagePath);
		if(srcImg.exists()){
			 // ImageIO 支持的图片类型 : [BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]
            String types = Arrays.toString(ImageIO.getReaderFormatNames()).replace("]", ",");
            String suffix = null;
            // 获取图片后缀
            if(srcImg.getName().indexOf(".") > -1) {
                suffix = srcImg.getName().substring(srcImg.getName().lastIndexOf(".") + 1);
            }
            // 类型和图片后缀全部小写，然后判断后缀是否合法
            if(suffix == null || types.toLowerCase().indexOf(suffix.toLowerCase()+",") < 0){
                log.error("Sorry, the image suffix is illegal. the standard image suffix is {}." + types);
                return false;
            }
		}
		return true;
	}
	
	/**
	* 验证图片后缀
	* 
	* @param imageName 图片名称
	* @return 如果是符合的字符串,返回 <b>true </b>,否则为 <b>false </b>
	*/
	public static Boolean imageName(String imageName){
		// ImageIO 支持的图片类型 : [BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]
        String types = Arrays.toString(ImageIO.getReaderFormatNames()).replace("]", ",");
        String suffix = null;
        // 获取图片后缀
        if(imageName.indexOf(".") > -1) {
            suffix = imageName.substring(imageName.lastIndexOf(".") + 1);
        }
        // 类型和图片后缀全部小写，然后判断后缀是否合法
        if(suffix == null || types.toLowerCase().indexOf(suffix.toLowerCase()+",") < 0){
            log.error("Sorry, the image suffix is illegal. the standard image suffix is {}." + types);
            return false;
        }
		return true;
	}
	
	 /**
	 * <p>Title: thumbnailImage</p>
	 * <p>Description: 根据图片路径生成缩略图 </p>
	 * @param imagePath    原图片路径
	 * @param w            缩略图宽
	 * @param h            缩略图高
	 * @param force        是否强制按照宽高生成缩略图(如果为false，则生成最佳比例缩略图)
	 */
    public static void thumbnailImage(File srcImg, OutputStream output, int w, int h, boolean force){
        if(srcImg.exists()){
            try {
                // ImageIO 支持的图片类型 : [BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]
                String types = Arrays.toString(ImageIO.getReaderFormatNames()).replace("]", ",");
                String suffix = null;
                // 获取图片后缀
                if(srcImg.getName().indexOf(".") > -1) {
                    suffix = srcImg.getName().substring(srcImg.getName().lastIndexOf(".") + 1);
                }// 类型和图片后缀全部小写，然后判断后缀是否合法
                if(suffix == null || types.toLowerCase().indexOf(suffix.toLowerCase()+",") < 0){
                    log.error("Sorry, the image suffix is illegal. the standard image suffix is {}." + types);
                    return ;
                }
                //log.debug("target image's size, width:{}, height:{}.",w,h);
                Image img = ImageIO.read(srcImg);
                // 根据原图与要求的缩略图比例，找到最合适的缩略图比例
                if(!force){
                    int width = img.getWidth(null);
                    int height = img.getHeight(null);
                    if((width*1.0)/w < (height*1.0)/h){
                        if(width > w){
                            h = Integer.parseInt(new java.text.DecimalFormat("0").format(height * w/(width*1.0)));
                            //log.debug("change image's height, width:{}, height:{}.",w,h);
                        }
                    } else {
                        if(height > h){
                            w = Integer.parseInt(new java.text.DecimalFormat("0").format(width * h/(height*1.0)));
                            //log.debug("change image's width, width:{}, height:{}.",w,h);
                        }
                    }
                }
                BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                Graphics g = bi.getGraphics();
                g.drawImage(img, 0, 0, w, h, Color.LIGHT_GRAY, null);
                g.dispose();
                // 将图片保存在原目录并加上前缀
                ImageIO.write(bi, suffix, output);
                output.close();
            } catch (IOException e) {
               log.error("generate thumbnail image failed.",e);
            }
        }else{
            log.warn("the src image is not exist.");
        }
    }
    /**
	 * 存缩略图片
	 * @param srcImg 文件
	 * @param w 图片宽
	 * @param h 图片高
	 * @param size 图片后缀(尺寸)
	 * @return
	 */
    public static String thumbnailImage(File srcImg, int w, int h, String size, boolean force){
        String absolutePath = srcImg.getAbsolutePath();
        String filePath="";
        try {
            if(!srcImg.isDirectory()) absolutePath = srcImg.getParent();
            if(!absolutePath.endsWith(File.separator)) absolutePath = absolutePath + File.separator;
            String srcFileName=srcImg.getName();
            int index=srcFileName.indexOf(".");
            filePath= absolutePath  + (srcFileName.substring(0,index))+size+(srcFileName.substring(index));
            java.io.FileOutputStream output=new java.io.FileOutputStream(filePath);
            thumbnailImage(srcImg, output, w, h, force);
        } catch (FileNotFoundException e) {
            log.error("the dest image is not exist.",e);
        }
        return filePath;
    }
    
    /**
	 * 存缩略图片
	 * @param srcImg 文件
	 * @param size 图片后缀(尺寸)
	 * @param w 图片宽
	 * @param h 图片高
	 * @return 图片路径
	 */
    public static String thumbnailImage(String imagePath, int w, int h, String size, boolean force){
    	//System.out.println(imagePath);
        File srcImg = new File(imagePath);
        return thumbnailImage(srcImg, w, h, size, force);
    }
    /**
	 * 存缩略图片
	 * @param imagePath 图片路径
	 * @param size 图片后缀(尺寸)
	 * @param w 图片宽
	 * @param h 图片高
	 * @param DEFAULT_FORCE 为false，生成最佳比例缩略图
	 * @return
	 */
    public static String thumbnailImage(String imagePath, int w, int h,String prevfix){
        return thumbnailImage(imagePath, w, h,prevfix, DEFAULT_FORCE);
    }
    
    /**
     * <p>Title: cutImage</p>
     * <p>Description:  根据原图与裁切size截取局部图片</p>
     * @param srcImg    源图片
     * @param output    图片输出流
     * @param rect        需要截取部分的坐标和大小
     */
    public static void cutImage(File srcImg, OutputStream output, java.awt.Rectangle rect){
        if(srcImg.exists()){
            java.io.FileInputStream fis = null;
            ImageInputStream iis = null;
            try {
                fis = new FileInputStream(srcImg);
                // ImageIO 支持的图片类型 : [BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]
                String types = Arrays.toString(ImageIO.getReaderFormatNames()).replace("]", ",");
                String suffix = null;
                // 获取图片后缀
                if(srcImg.getName().indexOf(".") > -1) {
                    suffix = srcImg.getName().substring(srcImg.getName().lastIndexOf(".") + 1);
                }// 类型和图片后缀全部小写，然后判断后缀是否合法
                if(suffix == null || types.toLowerCase().indexOf(suffix.toLowerCase()+",") < 0){
                    log.error("Sorry, the image suffix is illegal. the standard image suffix is {}." + types);
                    return ;
                }
                // 将FileInputStream 转换为ImageInputStream
                iis = ImageIO.createImageInputStream(fis);
                // 根据图片类型获取该种类型的ImageReader
                ImageReader reader = ImageIO.getImageReadersBySuffix(suffix).next();
                reader.setInput(iis,true);
                ImageReadParam param = reader.getDefaultReadParam();
                param.setSourceRegion(rect);
                BufferedImage bi = reader.read(0, param);
                ImageIO.write(bi, suffix, output);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if(fis != null) fis.close();
                    if(iis != null) iis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }else {
            log.warn("the src image is not exist.");
        }
    }
    /**
	 * 剪切图片
	 * @param srcImg 源图片
	 * @param output    图片输出流
	 * @param x 截取x坐标
	 * @param y 截取y坐标
	 * @param width 截取宽
	 * @param height 截取高
	 * @return
	 */
    public void cutImage(File srcImg, OutputStream output, int x, int y, int width, int height){
        cutImage(srcImg, output, new java.awt.Rectangle(x, y, width, height));
    }
    
    /**
	 * 剪切图片
	 * @param srcImg 图片路径
	 * @param size 图片后缀(尺寸)
	 * @param rect  需要截取部分的坐标和大小
	 * @return
	 */
    public static void cutImage(File srcImg,String size, java.awt.Rectangle rect){
        String absolutePath = srcImg.getAbsolutePath();
        try {
            if(!srcImg.isDirectory()) absolutePath = srcImg.getParent();
            if(!absolutePath.endsWith(File.separator)) absolutePath = absolutePath + File.separator;
            String srcFileName=srcImg.getName();
            int index=srcFileName.indexOf("_");
            int index2=srcFileName.indexOf(".");
            String filePath= absolutePath  + (srcFileName.substring(0,index))+size+(srcFileName.substring(index2));
            java.io.FileOutputStream output=new java.io.FileOutputStream(filePath);
            cutImage(srcImg, output, rect);
        } catch (FileNotFoundException e) {
            log.error("the dest image is not exist.",e);
        }
    }
    
    public void cutImage(File srcImg, String prevfix, int x, int y, int width, int height){
        cutImage(srcImg,prevfix, new java.awt.Rectangle(x, y, width, height));
    }
    
    public static void cutImage(String srcImg,String prevfix, int x, int y, int width, int height){
        cutImage(new File(srcImg),prevfix, new java.awt.Rectangle(x, y, width, height));
    }
    /**
	 * 中心剪切图片
	 * @param srcImg 图片路径
	 * @param size 图片后缀(尺寸)
	 * @param width 图片宽
	 * @param height 图片高
	 * @return
	 */
    public static void cutImage(String srcImg,String size,int width, int height){
    	System.out.println("####################srcImg:  "+srcImg);
    	File imageFile=new File(srcImg);
    	int x = 0;
    	int y = 0;
    	BufferedImage image;
		try {
			image = ImageIO.read(imageFile);
			Integer imageWidth = image.getWidth();  
			Integer imageHeight = image.getHeight();  
			double i = (double) imageWidth / (double) imageHeight;  
			double j = (double) width / (double) height;
			int[] d = new int[2];
			if (i > j) {  
				d[1] = height;  
				d[0] = (int) (height * i);  
				y = 0;  
				x = (d[0] - width) / 2;  
			} else {  
				d[0] = width;  
				d[1] = (int) (width / i);  
				x = 0;  
				y = (d[1] - height) / 2;
			}
			//System.out.println("x:"+x+"y:"+y);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
        cutImage(imageFile,size, new java.awt.Rectangle(x, y, width, height));
    }
    
    /**
	 * 存图片-生成缩略图-剪切-删除缩略图
	 * @param srcImg 图片路径开头
	 * @param reportImgName 图片名称
	 * @param thumbnailSuffix 图片裁剪后缀
	 * @param prevfix 存缩略格式前缀
	 * @param width 图片宽
	 * @param height 图片高
	 * @return
	 */
    public static void thumbnailCutImage(String srcImg,String reportImgName,String thumbnailSuffix,String size,int width, int height){
    	String path=ImageUtil.thumbnailImage(srcImg+reportImgName, width, height,thumbnailSuffix);
    	ImageUtil.cutImage(path,size,width, height);
    	File f = new File(path);
        f.delete();
    }
    
    public static void main(String[] args) {
    	ImageUtil.thumbnailCutImage("D:\\files\\images\\Banner\\2017\\06\\","Gui10038.jpeg",thumbnailSuffix,ImageUtil.thumbnailSize200_200,200,200);
    	//ImageUtil.thumbnailCutImage("D:\\images\\Banner\\2017\\06\\","Ban10090.png",thumbnailSuffix,ImageUtil.thumbnailSize500_200,500,200);
    	System.out.println(ImageUtil.imageName("imageName.png"));
    }
    
	
	
	/**
	 * 输出图片文件
	 * @param imageBase64Str 图片base64加密后的字符串
	 * @param fileName 输出图片文件名
	 * @return
	 */
	public static String writeImage(String imageBase64Str,String fileName){
		OutputStream os=null;
		try{
			byte[]imageByte=Base64Util.decode(imageBase64Str);
			os=new FileOutputStream(fileName);
			os.write(imageByte);
		}catch (Exception e) {
			e.printStackTrace();
			log.error("Write Image Error,FileName: "+fileName+" Exception: "+e.getMessage());
			return null;
		}finally{
			try {
				os.flush();
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return fileName;
	}
	
}
